package org.jeecg.common.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;

import java.io.*;
import java.util.Optional;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 文件工具
 */
@Slf4j
public class FileUtil {
    private static final String jarFlag = ".jar!";

    /**
     * 	创建文件目录
     *
     * @param dir
     */
    public static void mkdirs(String dir) {
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    /**
     * 根据文件名称获取ContentType
     * @param fileName
     * @return
     */
    public static String getContentType(String fileName){
        Optional<MediaType> mediaType = MediaTypeFactory.getMediaType(fileName);
        return mediaType.orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
    }

    /**
     * 将InputStream写入本地文件
     * @param destination 写入本地目录
     * @param input	输入流
     * @throws IOException
     */
    public static void writeToLocal(String destination, InputStream input) throws IOException {
        int index;
        byte[] bytes = new byte[1024];
        FileOutputStream downloadFile = null;
        try {
            File file = new File(destination);
            if(!file.exists()){
                file.getParentFile().mkdirs();
            }
            downloadFile = new FileOutputStream(destination);
            while ((index = input.read(bytes)) != -1) {
                downloadFile.write(bytes, 0, index);
            }
            downloadFile.flush();
        } finally {
            try {
                if(downloadFile != null) {
                    downloadFile.close();
                }
            } catch (Exception e) {}
            try {
                if(input != null) {
                    input.close();
                }
            } catch (Exception e) {}
        }
    }

    /**
     * 将源目录下的文件复制到目录目录下， 包括子目录
     * @param sourceDir
     * @param targetDir
     */
    public static void copyFolderToFolder(String sourceDir, String targetDir) throws IOException {
        copyFolderToFolder(sourceDir, File.separator, targetDir);
    }

    private static void copyFolderToFolder(String sourceDir, String filePath, String targetDir) throws IOException {
        File[] sourceDirs = new File(sourceDir).listFiles();
        if(sourceDirs == null){
            return;
        }
        for(File file: sourceDirs){
            if(file.isFile()){
                String path = targetDir + filePath + file.getName();
                writeToLocal(path, new FileInputStream(file));
            } else if(file.isDirectory()) {
                copyFolderToFolder(file.getPath(), filePath + file.getName() + File.separator, targetDir);
            }
        }
    }

    public static String specialPathHandle(String path){
        int bindex = path.indexOf("ADMINI~");
        if(bindex > 0){
            int eindex = path.indexOf(File.separator, bindex);
            String repStr = path.substring(bindex, eindex);
            path = path.replace(repStr, "Administrator");
        }
        return path;
    }

    /**
     * 读取文件， 兼容读取jar中的文件。
     * @param filePath
     * @return
     * @throws FileNotFoundException
     */
    public static InputStream getResource(String filePath) throws IOException {
        InputStream inputStream = null;
        if(filePath.contains(jarFlag)){
            filePath = filePath.replace("\\", "/").replace("//", "/");
            if(filePath.startsWith("file:")){
                filePath = filePath.substring("file:".length());
            }
            JarFile jarFile = null;
            InputStream is = null;
            try{
                String jarPath = filePath.substring(0, filePath.indexOf(jarFlag) + jarFlag.length() - 1);
                String file = filePath.substring(filePath.indexOf(jarFlag) + jarFlag.length() + 1).replace("classes!", "classes");
                jarFile = new JarFile(jarPath);
                JarEntry entry = jarFile.getJarEntry(file);
                is = jarFile.getInputStream(entry);
            } catch (Exception e){
                try{
                    is.close();
                } catch (Exception e1){}

                try{
                    jarFile.close();
                } catch (Exception e1){}
            }

            if (is != null){
                JarFile newJarFile = jarFile;
                InputStream newIs = is;
                inputStream = new InputStream() {
                    @Override
                    public int read() throws IOException {
                        return newIs.read();
                    }

                    @Override
                    public int read(byte[] b) throws IOException {
                        return newIs.read(b);
                    }

                    @Override
                    public int read(byte[] b, int off, int len) throws IOException {
                        return newIs.read(b, off, len);
                    }

                    @Override
                    public long skip(long n) throws IOException {
                        return newIs.skip(n);
                    }

                    @Override
                    public int available() throws IOException {
                        return newIs.available();
                    }

                    @Override
                    public void close() throws IOException {
                        try{
                            newIs.close();
                        } catch (Exception e){}

                        try{
                            newJarFile.close();
                        } catch (Exception e){}
                    }

                    @Override
                    public synchronized void mark(int readlimit) {
                        newIs.mark(readlimit);
                    }

                    @Override
                    public synchronized void reset() throws IOException {
                        newIs.reset();
                    }

                    @Override
                    public boolean markSupported() {
                        return newIs.markSupported();
                    }
                };
            }
        } else {
            inputStream = new FileInputStream(filePath);
        }
        return inputStream;
    }

    /**
     * 递归删除目录
     *
     * @param path
     */
    public static void delDir(String path) {
        if (StringUtils.isBlank(path)) {
            return;
        }
        File dir = new File(path);
        if (dir.exists()) {
            File[] tmp = dir.listFiles();
            if (tmp != null) {
                for (int i = 0; i < tmp.length; i++) {
                    if (tmp[i].isDirectory()) {
                        delDir(path + "/" + tmp[i].getName());
                    } else {
                        tmp[i].delete();
                    }
                }
            }
            dir.delete();
        }
    }

    /**
     * 删除文件
     * @return
     */
    public static boolean delFile(String filePath){
        if(filePath == null){
            return false;
        }
        File file = new File(filePath);
        if(!file.isFile()){
            return false;
        }
        return file.delete();
    }

}
